<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.10.0" />
<title>silk.transforms.cv.homography API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>silk.transforms.cv.homography</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python"># Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.

# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.

from typing import Optional, Tuple, Union

import torch
from silk.config.sampler import Sampler
from silk.cv.homography import HomographicSampler
from silk.transforms.abstract import Transform


class RandomHomographicSampler(Transform, HomographicSampler):
    &#34;&#34;&#34;`silk.cv.homography.HomographicSampler` with an easy way to randomize homographies into easy to control linear transforms.&#34;&#34;&#34;

    def __init__(
        self,
        batch_size: int,
        sampling_size: Tuple[int, int],
        sampling_mode: str = &#34;bilinear&#34;,
        scaling_sampler: Union[Sampler, None] = None,
        x_rotation_sampler: Union[Sampler, None] = None,
        y_rotation_sampler: Union[Sampler, None] = None,
        z_rotation_sampler: Union[Sampler, None] = None,
        x_translation_sampler: Union[Sampler, None] = None,
        y_translation_sampler: Union[Sampler, None] = None,
        auto_randomize: bool = True,
        device: Optional[str] = None,
    ) -&gt; None:
        &#34;&#34;&#34;
        Parameters
        ----------
        batch_size : int
            Number of virtual crops.
        sampling_size : Tuple[int, int]
            Spatial shape of generated output crops.
        sampling_mode : str, optional
            Sampling mode passed to `grid_sample`, by default &#34;bilinear&#34;
        scaling_sampler : Union[Sampler, None], optional
            Scaling factor sampler, by default None
        x_rotation_sampler : Union[Sampler, None], optional
            x-axis rotation (out-of-plane) sampler, by default None
        y_rotation_sampler : Union[Sampler, None], optional
            y-axis rotation (out-of-plane) sampler, by default None
        z_rotation_sampler : Union[Sampler, None], optional
            z-axis rotation (in-plane) sampler, by default None
        x_translation_sampler : Union[Sampler, None], optional
            horizontal translation sampler, by default None
        y_translation_sampler : Union[Sampler, None], optional
            vertical translation sampler, by default None
        auto_randomize : bool, optional
            Automatically call the `randomize` function when calling `forward_sampling` or `backward_sampling`, by default True
        device : Optional[str], optional
            Device used for sampling, by default None
        &#34;&#34;&#34;
        Transform.__init__(self)
        HomographicSampler.__init__(self, batch_size, device)

        self._sampling_size = sampling_size
        self._sampling_mode = sampling_mode

        self._auto_randomize = auto_randomize

        self._scaling_sampler = scaling_sampler
        self._x_rotation_sampler = x_rotation_sampler
        self._y_rotation_sampler = y_rotation_sampler
        self._z_rotation_sampler = z_rotation_sampler
        self._x_translation_sampler = x_translation_sampler
        self._y_translation_sampler = y_translation_sampler

    @property
    def sampling_size(self):
        return self._sampling_size

    def randomize(self):
        &#34;&#34;&#34;Generate random homographic transform parameters.&#34;&#34;&#34;
        self.reset()

        # 1. rescale
        if self._scaling_sampler:
            scaling_factors = self._scaling_sampler(
                shape=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )
            self.scale(scaling_factors)

        # 2. rotations
        def _rot(rot_sampler, axis):
            if rot_sampler:
                angles = rot_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
                self.rotate(angles, axis=axis)

        _rot(self._x_rotation_sampler, &#34;x&#34;)
        _rot(self._y_rotation_sampler, &#34;y&#34;)
        _rot(self._z_rotation_sampler, &#34;z&#34;)

        # 3. shift crop
        if self._x_translation_sampler or self._y_translation_sampler:
            if self._x_translation_sampler:
                x_translations = self._x_translation_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
            else:
                x_translations = torch.zeros(
                    size=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )

            if self._y_translation_sampler:
                y_translations = self._y_translation_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
            else:
                y_translations = torch.zeros(
                    size=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )

            shift_deltas = torch.cat((x_translations, y_translations), dim=1)
            self.shift(shift_deltas)

        # TODO(Pierre): Add mechanism to make sure sampling stays inside the original image

    def _sample(
        self, images: torch.Tensor, randomize=None, direction=&#34;forward&#34;
    ) -&gt; torch.Tensor:
        if (randomize is None and self._auto_randomize) or randomize:
            self.randomize()

        return self.extract_crop(
            images, self._sampling_size, mode=self._sampling_mode, direction=direction
        )

    def forward_sampling(
        self, images: torch.Tensor, randomize: Optional[bool] = None
    ) -&gt; torch.Tensor:
        &#34;&#34;&#34;Sample crops from randomly generated homographies.

        Parameters
        ----------
        images : torch.Tensor
            Images to extract the crops from.
        randomize : bool, optional
            Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

        Returns
        -------
        torch.Tensor
            Generated crops.
        &#34;&#34;&#34;
        return self._sample(images, randomize, &#34;forward&#34;)

    def backward_sampling(self, images: torch.Tensor, randomize=None) -&gt; torch.Tensor:
        &#34;&#34;&#34;Reverse operation of `forward_sampling` (i.e. position provided crops into original image).

        Parameters
        ----------
        images : torch.Tensor
            Images to extract the crops from.
        randomize : bool, optional
            Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

        Returns
        -------
        torch.Tensor
            Generated crops.
        &#34;&#34;&#34;
        return self._sample(images, randomize, &#34;backward&#34;)

    __call__ = forward_sampling</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler"><code class="flex name class">
<span>class <span class="ident">RandomHomographicSampler</span></span>
<span>(</span><span>batch_size: int, sampling_size: Tuple[int, int], sampling_mode: str = 'bilinear', scaling_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, x_rotation_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, y_rotation_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, z_rotation_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, x_translation_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, y_translation_sampler: Optional[<a title="silk.config.sampler.Sampler" href="../../config/sampler.html#silk.config.sampler.Sampler">Sampler</a>] = None, auto_randomize: bool = True, device: Optional[str] = None)</span>
</code></dt>
<dd>
<div class="desc"><p><code><a title="silk.cv.homography.HomographicSampler" href="../../cv/homography.html#silk.cv.homography.HomographicSampler">HomographicSampler</a></code> with an easy way to randomize homographies into easy to control linear transforms.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>batch_size</code></strong> :&ensp;<code>int</code></dt>
<dd>Number of virtual crops.</dd>
<dt><strong><code>sampling_size</code></strong> :&ensp;<code>Tuple[int, int]</code></dt>
<dd>Spatial shape of generated output crops.</dd>
<dt><strong><code>sampling_mode</code></strong> :&ensp;<code>str</code>, optional</dt>
<dd>Sampling mode passed to <code>grid_sample</code>, by default "bilinear"</dd>
<dt><strong><code>scaling_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>Scaling factor sampler, by default None</dd>
<dt><strong><code>x_rotation_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>x-axis rotation (out-of-plane) sampler, by default None</dd>
<dt><strong><code>y_rotation_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>y-axis rotation (out-of-plane) sampler, by default None</dd>
<dt><strong><code>z_rotation_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>z-axis rotation (in-plane) sampler, by default None</dd>
<dt><strong><code>x_translation_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>horizontal translation sampler, by default None</dd>
<dt><strong><code>y_translation_sampler</code></strong> :&ensp;<code>Union[Sampler, None]</code>, optional</dt>
<dd>vertical translation sampler, by default None</dd>
<dt><strong><code>auto_randomize</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Automatically call the <code>randomize</code> function when calling <code>forward_sampling</code> or <code>backward_sampling</code>, by default True</dd>
<dt><strong><code>device</code></strong> :&ensp;<code>Optional[str]</code>, optional</dt>
<dd>Device used for sampling, by default None</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class RandomHomographicSampler(Transform, HomographicSampler):
    &#34;&#34;&#34;`silk.cv.homography.HomographicSampler` with an easy way to randomize homographies into easy to control linear transforms.&#34;&#34;&#34;

    def __init__(
        self,
        batch_size: int,
        sampling_size: Tuple[int, int],
        sampling_mode: str = &#34;bilinear&#34;,
        scaling_sampler: Union[Sampler, None] = None,
        x_rotation_sampler: Union[Sampler, None] = None,
        y_rotation_sampler: Union[Sampler, None] = None,
        z_rotation_sampler: Union[Sampler, None] = None,
        x_translation_sampler: Union[Sampler, None] = None,
        y_translation_sampler: Union[Sampler, None] = None,
        auto_randomize: bool = True,
        device: Optional[str] = None,
    ) -&gt; None:
        &#34;&#34;&#34;
        Parameters
        ----------
        batch_size : int
            Number of virtual crops.
        sampling_size : Tuple[int, int]
            Spatial shape of generated output crops.
        sampling_mode : str, optional
            Sampling mode passed to `grid_sample`, by default &#34;bilinear&#34;
        scaling_sampler : Union[Sampler, None], optional
            Scaling factor sampler, by default None
        x_rotation_sampler : Union[Sampler, None], optional
            x-axis rotation (out-of-plane) sampler, by default None
        y_rotation_sampler : Union[Sampler, None], optional
            y-axis rotation (out-of-plane) sampler, by default None
        z_rotation_sampler : Union[Sampler, None], optional
            z-axis rotation (in-plane) sampler, by default None
        x_translation_sampler : Union[Sampler, None], optional
            horizontal translation sampler, by default None
        y_translation_sampler : Union[Sampler, None], optional
            vertical translation sampler, by default None
        auto_randomize : bool, optional
            Automatically call the `randomize` function when calling `forward_sampling` or `backward_sampling`, by default True
        device : Optional[str], optional
            Device used for sampling, by default None
        &#34;&#34;&#34;
        Transform.__init__(self)
        HomographicSampler.__init__(self, batch_size, device)

        self._sampling_size = sampling_size
        self._sampling_mode = sampling_mode

        self._auto_randomize = auto_randomize

        self._scaling_sampler = scaling_sampler
        self._x_rotation_sampler = x_rotation_sampler
        self._y_rotation_sampler = y_rotation_sampler
        self._z_rotation_sampler = z_rotation_sampler
        self._x_translation_sampler = x_translation_sampler
        self._y_translation_sampler = y_translation_sampler

    @property
    def sampling_size(self):
        return self._sampling_size

    def randomize(self):
        &#34;&#34;&#34;Generate random homographic transform parameters.&#34;&#34;&#34;
        self.reset()

        # 1. rescale
        if self._scaling_sampler:
            scaling_factors = self._scaling_sampler(
                shape=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )
            self.scale(scaling_factors)

        # 2. rotations
        def _rot(rot_sampler, axis):
            if rot_sampler:
                angles = rot_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
                self.rotate(angles, axis=axis)

        _rot(self._x_rotation_sampler, &#34;x&#34;)
        _rot(self._y_rotation_sampler, &#34;y&#34;)
        _rot(self._z_rotation_sampler, &#34;z&#34;)

        # 3. shift crop
        if self._x_translation_sampler or self._y_translation_sampler:
            if self._x_translation_sampler:
                x_translations = self._x_translation_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
            else:
                x_translations = torch.zeros(
                    size=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )

            if self._y_translation_sampler:
                y_translations = self._y_translation_sampler(
                    shape=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )
            else:
                y_translations = torch.zeros(
                    size=(self.batch_size, 1),
                    device=self.device,
                    dtype=self.dtype,
                )

            shift_deltas = torch.cat((x_translations, y_translations), dim=1)
            self.shift(shift_deltas)

        # TODO(Pierre): Add mechanism to make sure sampling stays inside the original image

    def _sample(
        self, images: torch.Tensor, randomize=None, direction=&#34;forward&#34;
    ) -&gt; torch.Tensor:
        if (randomize is None and self._auto_randomize) or randomize:
            self.randomize()

        return self.extract_crop(
            images, self._sampling_size, mode=self._sampling_mode, direction=direction
        )

    def forward_sampling(
        self, images: torch.Tensor, randomize: Optional[bool] = None
    ) -&gt; torch.Tensor:
        &#34;&#34;&#34;Sample crops from randomly generated homographies.

        Parameters
        ----------
        images : torch.Tensor
            Images to extract the crops from.
        randomize : bool, optional
            Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

        Returns
        -------
        torch.Tensor
            Generated crops.
        &#34;&#34;&#34;
        return self._sample(images, randomize, &#34;forward&#34;)

    def backward_sampling(self, images: torch.Tensor, randomize=None) -&gt; torch.Tensor:
        &#34;&#34;&#34;Reverse operation of `forward_sampling` (i.e. position provided crops into original image).

        Parameters
        ----------
        images : torch.Tensor
            Images to extract the crops from.
        randomize : bool, optional
            Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

        Returns
        -------
        torch.Tensor
            Generated crops.
        &#34;&#34;&#34;
        return self._sample(images, randomize, &#34;backward&#34;)

    __call__ = forward_sampling</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="silk.transforms.abstract.Transform" href="../abstract.html#silk.transforms.abstract.Transform">Transform</a></li>
<li>torch.nn.modules.module.Module</li>
<li><a title="silk.cv.homography.HomographicSampler" href="../../cv/homography.html#silk.cv.homography.HomographicSampler">HomographicSampler</a></li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.dump_patches"><code class="name">var <span class="ident">dump_patches</span> : bool</code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.training"><code class="name">var <span class="ident">training</span> : bool</code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Instance variables</h3>
<dl>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.sampling_size"><code class="name">var <span class="ident">sampling_size</span></code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">@property
def sampling_size(self):
    return self._sampling_size</code></pre>
</details>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.backward_sampling"><code class="name flex">
<span>def <span class="ident">backward_sampling</span></span>(<span>self, images: torch.Tensor, randomize=None) ‑> torch.Tensor</span>
</code></dt>
<dd>
<div class="desc"><p>Reverse operation of <code>forward_sampling</code> (i.e. position provided crops into original image).</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>images</code></strong> :&ensp;<code>torch.Tensor</code></dt>
<dd>Images to extract the crops from.</dd>
<dt><strong><code>randomize</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites <code>auto_randomize</code> option.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>torch.Tensor</code></dt>
<dd>Generated crops.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def backward_sampling(self, images: torch.Tensor, randomize=None) -&gt; torch.Tensor:
    &#34;&#34;&#34;Reverse operation of `forward_sampling` (i.e. position provided crops into original image).

    Parameters
    ----------
    images : torch.Tensor
        Images to extract the crops from.
    randomize : bool, optional
        Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

    Returns
    -------
    torch.Tensor
        Generated crops.
    &#34;&#34;&#34;
    return self._sample(images, randomize, &#34;backward&#34;)</code></pre>
</details>
</dd>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.forward_sampling"><code class="name flex">
<span>def <span class="ident">forward_sampling</span></span>(<span>self, images: torch.Tensor, randomize: Optional[bool] = None) ‑> torch.Tensor</span>
</code></dt>
<dd>
<div class="desc"><p>Sample crops from randomly generated homographies.</p>
<h2 id="parameters">Parameters</h2>
<dl>
<dt><strong><code>images</code></strong> :&ensp;<code>torch.Tensor</code></dt>
<dd>Images to extract the crops from.</dd>
<dt><strong><code>randomize</code></strong> :&ensp;<code>bool</code>, optional</dt>
<dd>Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites <code>auto_randomize</code> option.</dd>
</dl>
<h2 id="returns">Returns</h2>
<dl>
<dt><code>torch.Tensor</code></dt>
<dd>Generated crops.</dd>
</dl></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def forward_sampling(
    self, images: torch.Tensor, randomize: Optional[bool] = None
) -&gt; torch.Tensor:
    &#34;&#34;&#34;Sample crops from randomly generated homographies.

    Parameters
    ----------
    images : torch.Tensor
        Images to extract the crops from.
    randomize : bool, optional
        Randomize before sampling (otherwise use previous randomly generated homographies), by default None. Overwrites `auto_randomize` option.

    Returns
    -------
    torch.Tensor
        Generated crops.
    &#34;&#34;&#34;
    return self._sample(images, randomize, &#34;forward&#34;)</code></pre>
</details>
</dd>
<dt id="silk.transforms.cv.homography.RandomHomographicSampler.randomize"><code class="name flex">
<span>def <span class="ident">randomize</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Generate random homographic transform parameters.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def randomize(self):
    &#34;&#34;&#34;Generate random homographic transform parameters.&#34;&#34;&#34;
    self.reset()

    # 1. rescale
    if self._scaling_sampler:
        scaling_factors = self._scaling_sampler(
            shape=(self.batch_size, 1),
            device=self.device,
            dtype=self.dtype,
        )
        self.scale(scaling_factors)

    # 2. rotations
    def _rot(rot_sampler, axis):
        if rot_sampler:
            angles = rot_sampler(
                shape=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )
            self.rotate(angles, axis=axis)

    _rot(self._x_rotation_sampler, &#34;x&#34;)
    _rot(self._y_rotation_sampler, &#34;y&#34;)
    _rot(self._z_rotation_sampler, &#34;z&#34;)

    # 3. shift crop
    if self._x_translation_sampler or self._y_translation_sampler:
        if self._x_translation_sampler:
            x_translations = self._x_translation_sampler(
                shape=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )
        else:
            x_translations = torch.zeros(
                size=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )

        if self._y_translation_sampler:
            y_translations = self._y_translation_sampler(
                shape=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )
        else:
            y_translations = torch.zeros(
                size=(self.batch_size, 1),
                device=self.device,
                dtype=self.dtype,
            )

        shift_deltas = torch.cat((x_translations, y_translations), dim=1)
        self.shift(shift_deltas)

    # TODO(Pierre): Add mechanism to make sure sampling stays inside the original image</code></pre>
</details>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="silk.transforms.abstract.Transform" href="../abstract.html#silk.transforms.abstract.Transform">Transform</a></b></code>:
<ul class="hlist">
<li><code><a title="silk.transforms.abstract.Transform.forward" href="../abstract.html#silk.transforms.abstract.Transform.forward">forward</a></code></li>
</ul>
</li>
<li><code><b><a title="silk.cv.homography.HomographicSampler" href="../../cv/homography.html#silk.cv.homography.HomographicSampler">HomographicSampler</a></b></code>:
<ul class="hlist">
<li><code><a title="silk.cv.homography.HomographicSampler.extract_crop" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.extract_crop">extract_crop</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.reset" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.reset">reset</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.rotate" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.rotate">rotate</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.scale" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.scale">scale</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.shift" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.shift">shift</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.src_coords" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.src_coords">src_coords</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.to" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.to">to</a></code></li>
<li><code><a title="silk.cv.homography.HomographicSampler.transform_points" href="../../cv/homography.html#silk.cv.homography.HomographicSampler.transform_points">transform_points</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="silk.transforms.cv" href="index.html">silk.transforms.cv</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="silk.transforms.cv.homography.RandomHomographicSampler" href="#silk.transforms.cv.homography.RandomHomographicSampler">RandomHomographicSampler</a></code></h4>
<ul class="two-column">
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.backward_sampling" href="#silk.transforms.cv.homography.RandomHomographicSampler.backward_sampling">backward_sampling</a></code></li>
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.dump_patches" href="#silk.transforms.cv.homography.RandomHomographicSampler.dump_patches">dump_patches</a></code></li>
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.forward_sampling" href="#silk.transforms.cv.homography.RandomHomographicSampler.forward_sampling">forward_sampling</a></code></li>
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.randomize" href="#silk.transforms.cv.homography.RandomHomographicSampler.randomize">randomize</a></code></li>
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.sampling_size" href="#silk.transforms.cv.homography.RandomHomographicSampler.sampling_size">sampling_size</a></code></li>
<li><code><a title="silk.transforms.cv.homography.RandomHomographicSampler.training" href="#silk.transforms.cv.homography.RandomHomographicSampler.training">training</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
</footer>
</body>
</html>